#include<iostream>
#include<string>
#include <openssl/sha.h>
#include<openssl/md5.h>
#include<cctype>
#include "sv_node.hpp"
#include "my570list.hpp"
#include "cs570.h"

using namespace std;

extern My570List* kwrdList;
extern My570List* nameList;
extern My570List* sha1List;
extern My570List* nonceList;
extern My570List* fileidList;
extern char* HomeDir1;
extern unsigned char *node_instance_id;
extern pthread_mutex_t PermList_lock;

//extern string delFileName;
//extern string delSha1;
//extern string delNonce;



//--------------------------------------------------------- bitmap search -------------------------------------- begin-------------//


//unsigned char* bitmap_srch = new unsigned char[128];

void bitset_srch(int bit,unsigned char* bitmap_srch)
{ 
   int byte=0;
   int bitposition =0;

   byte = bit/8;

   bitposition = bit%8;

   bitmap_srch[127-byte] |=1 <<(bitposition);

}

void makeBitVector(string &temp1,unsigned char* bitmap_srch){

	unsigned char* shaResults = new unsigned char[20] ;
	unsigned char* md5Results = new unsigned char[20];
	int actualbit=0;
	int bitraise=0;
	int checkbit=0;

                          SHA1((const unsigned char*)temp1.c_str(),temp1.length(),shaResults);
						  bitraise = hex_to_int((unsigned char*)&shaResults[18],1);
								  checkbit=(bitraise&1);
								  if(checkbit==1){
									  actualbit=256+512;
								  }else{
									  actualbit=512;
								  }
								  bitraise = hex_to_int((unsigned char*)&shaResults[19],1);
								  actualbit=actualbit+bitraise;
								  bitset_srch(actualbit,bitmap_srch);
                          actualbit=0;
						  bitraise=0;
						  checkbit=0;
						  MD5((const unsigned char*)temp1.c_str(),temp1.length(),md5Results);				
						  bitraise = hex_to_int((unsigned char*)&md5Results[14],1);
								  checkbit = (bitraise&1);
								  
								  if(checkbit==1){
									  actualbit=256;
								  }else{
									  actualbit=0;
								  }
								  bitraise = hex_to_int((unsigned char*)&md5Results[15],1);
								  actualbit = actualbit+bitraise;
								  bitset_srch(actualbit,bitmap_srch);


 free(shaResults);
 free(md5Results);
 return;
}

//--------------------------------------------------------- bitmap search -------------------------------------- end----------------//







void remove_index(int i)
{
	//lock
	pthread_mutex_lock(&PermList_lock);
	
	 int LocalIndex=i;
	 if(kwrdList->Length()!=0){
     My570ListElem *remK = new My570ListElem();
	 for(remK=kwrdList->First();remK!=NULL;remK=kwrdList->Next(remK))
	     {
		    if(((Boot_Elem*)(remK->Obj()))->index==LocalIndex)
		     {
			 kwrdList->Unlink(remK);
		     }
	     }
		 delete remK;
	 }

	 if(nameList->Length()!=0){
     My570ListElem *remN = new My570ListElem();
	 for(remN=nameList->First();remN!=NULL;remN=kwrdList->Next(remN))
		 {
		    if(((Boot_Elem*)(remN->Obj()))->index==LocalIndex)
			 {
				nameList->Unlink(remN);
			 }
		 }
		 delete remN;
	 }

	 if(sha1List->Length()!=0){
     My570ListElem *remS = new My570ListElem();
	 for(remS=sha1List->First();remS!=NULL;remS=sha1List->Next(remS))
		 {
		    if(((Boot_Elem*)(remS->Obj()))->index==LocalIndex)
			 {
				sha1List->Unlink(remS);
			 }
		 }
		 delete remS;
	 }

	 if(nonceList->Length()!=0){
     My570ListElem *remO = new My570ListElem();
	 for(remO=nonceList->First();remO!=NULL;remO=sha1List->Next(remO))
		 {
		    if(((Boot_Elem*)(remO->Obj()))->index==LocalIndex)
			 {
				nonceList->Unlink(remO);
			 }
		 }
		 delete remO;
	 }

		if(fileidList->Length()!=0){
                        My570ListElem *felem = new My570ListElem();
                        for(felem=fileidList->First();felem!=NULL;felem=fileidList->Next(felem))
                        {
                                if(((Boot_Elem*)(felem->Obj()))->index==LocalIndex)
                                {
                                        fileidList->Unlink(felem);
                                }
                        }
						delete felem;
                }	 

    pthread_mutex_unlock(&PermList_lock);
    //unlock 
	return;
}

int sv_delete(const char* delFileName,const char* delSha1,const char* delNonce,int pwd)
{
	//pwdflag=pwd;

    //---------------------- convert strings to hex ----------------//

	//delSha1
	        unsigned char* hexstring1 = (unsigned char*)malloc(20);
			unsigned char* hex_delSha1 = (unsigned char*)malloc(20);
			unsigned char temp1;
            unsigned char temp2;
			int ik1=0;
			for(int i=0;i<40;i=i+2)
			{
				temp1=tohex(delSha1[i]);
				temp2=tohex(delSha1[i+1]);

				temp1=temp1<<4;

				hexstring1[ik1]=temp1 | temp2;
				ik1=ik1+1;
				
			}
			memcpy(hex_delSha1,hexstring1,20);
			free(hexstring1);

    //delNonce
	        unsigned char* hexstring2 = (unsigned char*)malloc(20);
			unsigned char* hex_delNonce = (unsigned char*)malloc(20);
			unsigned char temp3;
			unsigned char temp4;
			int ik2=0;
			for(int j=0;j<40;j=j+2)
	        {
				temp3=tohex(delNonce[j]);
				temp4=tohex(delNonce[j+1]);

				temp3=temp3<<4;

				hexstring2[ik2] = temp3 | temp4;
				ik2=ik2+1;
			}
			memcpy(hex_delNonce,hexstring2,20);
			free(hexstring2);


    //---------------------- convert strings to hex ----------------// 



	int LocalIndex=0; 
	int nameflag=0;
	int sha1flag=0;
	int nonceflag=0;
	int pwdflag=pwd;

	if(nameList->Length()!=0){
     
		My570ListElem* elem = new My570ListElem();
		for(elem=nameList->First();elem!=NULL;elem=nameList->Next(elem))
		{
			if(strcmp(string(((Boot_Elem*)(elem->Obj()))->FileName).c_str(),delFileName)==0)
			{
                LocalIndex=((Boot_Elem*)(elem->Obj()))->index;
				nameflag=1;
				//cout<<"match found"<<endl;
			}
		}
		delete elem;

	}//if namelist not null

	if(sha1List->Length()!=0){

		My570ListElem* elem = new My570ListElem();
		for(elem=sha1List->First();elem!=NULL;elem=sha1List->Next(elem))
		{
          if(((Boot_Elem*)(elem->Obj()))->index==LocalIndex)
			{
			  int n1=memcmp(((Boot_Elem*)(elem->Obj()))->Sha1,hex_delSha1,20);

			  if(n1==0)
				{
				//  cout<<"sha1 found"<<endl;
				  sha1flag=1;
				}
			}
		}
		delete elem;
	}//if sha1list not null

	if(nonceList->Length()!=0){

		My570ListElem* elem = new My570ListElem();
		for(elem=nonceList->First();elem!=NULL;elem=nonceList->Next(elem))
		{
			if(((Boot_Elem*)(elem->Obj()))->index==LocalIndex)
			{
				int n1=memcmp(((Boot_Elem*)(elem->Obj()))->Nonce,hex_delNonce,20);

				if(n1==0)
				{
				//	cout<<"nonce found"<<endl;
					nonceflag=1;
				}
                
				if(((Boot_Elem*)(elem->Obj()))->password==1)
				{
				//	cout<<"password found"<<endl;
					pwdflag=1;
				}
			}
		}
		delete elem;
	}//if noncelist not null

	if((nameflag==1) && (sha1flag==1) && (nonceflag==1) && (pwdflag==1))
	{
		//cout<<"delete file and remove from list"<<endl;

		string NodeHome = (string(HomeDir1)).substr(0,(int)strlen(HomeDir1)-1);
		string FilesHome = NodeHome + "/files";
        
		char myCurrName[100];
		sprintf(myCurrName,"%d",LocalIndex);
		string FileName = FilesHome +"/"+string(myCurrName) +".data";
        string MetaName = FilesHome +"/"+string(myCurrName) +".meta";
		remove(FileName.c_str());
		remove(MetaName.c_str());
		remove_index(LocalIndex);
        
		free(hex_delSha1);
	    free(hex_delNonce);
		return 1;

	}
	free(hex_delSha1);
	free(hex_delNonce);
	return 0;
}

////     search functions ///////////////-----------------------------------------------------///


void parse_meta(const char* filename)
{
    cout<<"    [1] "<<"FileID=";for(int i1=0;i1<20;i1++) printf("%02x",GetUOID(node_instance_id,"file")[i1]); cout<<endl;
	FILE* fp = fopen(filename,"r");
	int i=0;
	char* mystring=new char[300];
	while(!feof(fp)){
		fgets(mystring,300,fp);
		if(i==1)
		{
			cout<<"\t"<<string(mystring);
		}
		if(i==2)
		{
			cout<<"\t"<<string(mystring);
		}
		if(i==3)
		{
			cout<<"\t"<<string(mystring);
		}
		if(i==4)
		{
			cout<<"\t"<<string(mystring);
		}
		if(i==5)
		{
			cout<<"\t"<<string(mystring);
		}

      i=i+1; 

	}//while
delete mystring;
return;
}





int sv_searchName(string &fName)
{

		if(nameList->Length()!=0){
     
		My570ListElem* elem = new My570ListElem();
		for(elem=nameList->First();elem!=NULL;elem=nameList->Next(elem))
		{
			if(strcmp(string(((Boot_Elem*)(elem->Obj()))->FileName).c_str(),fName.c_str())==0)
			{				
				//cout<<"match found"<<endl;
				return ((Boot_Elem*)(elem->Obj()))->index;
			}
		}

	}//if namelist not null

return 0;
}

int sv_searchSha1(string &Sha1)
{
	//sha1
	        unsigned char* hexstring1 = (unsigned char*)malloc(20);
			unsigned char* hexSha1 = (unsigned char*)malloc(20);
			unsigned char temp1;
            unsigned char temp2;
			int ik1=0;
			for(int i=0;i<40;i=i+2)
			{
				temp1=tohex(Sha1[i]);
				temp2=tohex(Sha1[i+1]);

				temp1=temp1<<4;

				hexstring1[ik1]=temp1 | temp2;
				ik1=ik1+1;
				
			}
			memcpy(hexSha1,hexstring1,20);

		/*	for(int k=0;k<20;k++)
        	{
				printf("%02x",hexSha1[k]);
	        }
			cout<<endl;
*/
            // 
			if(sha1List->Length()!=0){

				My570ListElem* elem = new My570ListElem();
				for(elem=sha1List->First();elem!=NULL;elem=sha1List->Next(elem))
				{
					  int n1=memcmp(((Boot_Elem*)(elem->Obj()))->Sha1,hexSha1,20);

					  if(n1==0)
						{
					//	  cout<<"sha1 found"<<endl;

						  free(hexSha1);
                          free(hexstring1);
						  return ((Boot_Elem*)(elem->Obj()))->index;
						}
					
				}
			}//if sha1list not null    
free(hexSha1);
free(hexstring1);
return 0;
}

int sv_searchKeys(string &key)
{
	unsigned char* bitmap_srch = new unsigned char[128];
	memset(bitmap_srch,0,128);
	while(1)
	{
		string temp;
		int i=0;
		i=key.find_first_of(" ");
		if(i==-1){
			//cout<<key<<"*"<<endl;
			makeBitVector(key,bitmap_srch);
			//generate bitmap for key
			break;
		}
		temp=key.substr(0,i);
	//	cout<<temp<<"*"<<endl;
		makeBitVector(temp,bitmap_srch);
		key=key.substr(i+1,key.length()-i-1);

	}//while
/*
	for(int i=0;i<128;i++)
	{
		printf("%02x",bitmap_srch[i]);
	}
	cout<<endl;
*/
	//
	int n1=1;
	if(kwrdList->Length()!=0){
	    My570ListElem* elem = new My570ListElem();
		for(elem=kwrdList->First();elem!=NULL;elem=kwrdList->Next(elem))
		{
			unsigned char* bitmap_temp = new unsigned char[128];
			memset(bitmap_temp,0,128);

			for(int cy=0;cy<128;cy++){
				bitmap_temp[cy] = bitmap_srch[cy] | ((Boot_Elem*)(elem->Obj()))->Key[cy];
			}
			 n1=1;
			 n1=memcmp(((Boot_Elem*)(elem->Obj()))->Key,bitmap_temp,128);

					  if(n1==0)
						{
		/*				  cout<<"key found"<<endl;
						  for(int k=0;k<128;k++)
							{
							  printf("%02x",((Boot_Elem*)(elem->Obj()))->Key[k]);
							}
							  cout<<endl;
*/
                           delete bitmap_temp; 
                           delete bitmap_srch;  
						  return ((Boot_Elem*)(elem->Obj()))->index;
						}
          delete bitmap_temp; 
		}
	}
delete bitmap_srch;
return 0;
}




